package com.namecard.namecardapi.Task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.namecard.namecardapi.entity.CardInfo;
import com.namecard.namecardapi.entity.vo.CardAllInfoVO;
import com.namecard.namecardapi.entity.vo.DailyRandomCard;
import com.namecard.namecardapi.mapper.TagInfoMapper;
import com.namecard.namecardapi.service.CardInfoService;
import com.namecard.namecardapi.util.Constants;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 每天 00:10:00 开始将数据导入Redis
 * @author c_shunyi
 */
@Component
public class InsertRecommendedUserTask {

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    TagInfoMapper tagInfoMapper;
    @Autowired
    CardInfoService cardInfoService;

    /**
     * 自动添加每天推荐卡片
     */
    //@Scheduled(cron = "0 * * * * ?")
    @Scheduled(cron = "0 10 0 * * ?")
    public void insertRecommendedAllUser() throws JsonProcessingException {
        try {
            if (cardInfoService.duplicateUserId()){
                throw new RuntimeException("存在重复的用户，数据异常，无法添加数据到Redis中");
            }
            Map<String, String> userRandomTags = cardInfoService.list()
                    .stream()
                    .collect(Collectors.toMap(CardInfo::getUserId,
                            CardInfo ->{
                                JSONArray jsonArray = JSON.parseArray(CardInfo.getTagList());
                                List<String> tags = JSON.parseArray(jsonArray.toJSONString(), String.class);
                                if(tags.size() > 3){
                                    Collections.shuffle(tags);
                                    List<String> randomTags = tags.subList(0, 3);
                                    return JSON.toJSONString(randomTags);
                                }
                                return JSON.toJSONString(tags);
                            }));
            insertRecommendedUser(userRandomTags);
        }catch (RuntimeException e){
            System.out.println(e.getMessage());
        }
    }

    /**
     * 将处理后的数据插入redis中
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertRecommendedUser(Map<String, String> userRandomTags) {
        System.out.println("开启每日免费卡片插入Redis");
        String JsonRandomCardAllInfoVOs = "";
        DailyRandomCard dailyRandomCard = new DailyRandomCard();
        for (Map.Entry<String, String> entry : userRandomTags.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            Set<CardAllInfoVO> cardAllInfoVOS = new HashSet<>(60);
            // 处理tag
            List<String> tags = JSON.parseArray(value, String.class);
            for (String tag : tags) {
                cardAllInfoVOS.addAll(cardInfoService.getTop20(tag));
            }
            if (cardAllInfoVOS.size() > 20) {
                // 随机选择 20 条数据
                List<CardAllInfoVO> randomList = getRandomElements(cardAllInfoVOS, 20);
                List<CardAllInfoVO> cardAllInfoVOS1 = randomList.stream().map(CardAllInfoVO -> {
                    String userImage = CardAllInfoVO.getCardInfo().getUserImage();
                    if (userImage != null) {
                        CardAllInfoVO.getCardInfo().setUserImage("/img/avatar/" + userImage + ".jpg");
                        return CardAllInfoVO;
                    }
                    return CardAllInfoVO;
                }).collect(Collectors.toList());
                // 将随机选择的数据转换为 JSON 字符串
                JsonRandomCardAllInfoVOs = JSON.toJSONString(cardAllInfoVOS1);
                System.out.println(JsonRandomCardAllInfoVOs);
            } else {
                List<CardAllInfoVO> cardAllInfoVOS1 = cardAllInfoVOS.stream().map(CardAllInfoVO -> {
                    String userImage = CardAllInfoVO.getCardInfo().getUserImage();
                    if (userImage != null) {
                        CardAllInfoVO.getCardInfo().setUserImage("/img/avatar/" + userImage + ".jpg");
                        return CardAllInfoVO;
                    }
                    return CardAllInfoVO;
                }).collect(Collectors.toList());
                // 将所有数据转换为 JSON 字符串
                JsonRandomCardAllInfoVOs = JSON.toJSONString(cardAllInfoVOS1);
                System.out.println("用户卡片数据"+JsonRandomCardAllInfoVOs);
            }
            //存入Redis中
            dailyRandomCard.setRandomCardAllInfoToJson(JsonRandomCardAllInfoVOs);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String Date = sdf.format(new Date());
            String date = Date.substring(8, 10);
            dailyRandomCard.setDate(date);
            stringRedisTemplate.opsForValue().set("userCards:" + key, JSON.toJSONString(dailyRandomCard));
            stringRedisTemplate.expire("userCards:" + key, Constants.REDIS_USER_DATA_VALID_TIME, TimeUnit.MINUTES);
        }
    }

    /**
     * 获取随机元素
     */
    private static <T> List<T> getRandomElements(Set<T> set, int count) {
        List<T> list = new ArrayList<>(set);
        Random random = new Random();
        int size = list.size();
        for (int i = 0; i < count; i++) {
            int index = random.nextInt(size);
            T element = list.get(index);
            list.remove(index);
            size--;
            set.remove(element);
        }
        return list;
    }
}
